package com.nidu.demo.security.filter;

import cn.hutool.core.util.ObjectUtil;
import com.nidu.demo.common.exception.ErrorCodeConstants;
import com.nidu.demo.oauth2.gateway.OAuth2AccessTokenGateway;
import com.nidu.demo.oauth2.model.OAuth2AccessToken;
import com.nidu.demo.security.config.SecurityProperties;
import com.nidu.demo.security.core.LoginUser;
import com.nidu.demo.security.util.SecurityUtils;
import com.nidu.demo.web.util.WebUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * OAuth2认证过滤器 - 验证访问令牌并设置用户身份信息
 */
public class AuthenticationTokenFilter extends OncePerRequestFilter {

    private final OAuth2AccessTokenGateway accessTokenGateway;
    private final SecurityProperties securityProperties;

    public AuthenticationTokenFilter(SecurityProperties securityProperties, OAuth2AccessTokenGateway accessTokenGateway) {
        this.securityProperties = securityProperties;
        this.accessTokenGateway = accessTokenGateway;
    }

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException {
            // 获取访问令牌
        String token = SecurityUtils.getTokenFromRequest(request, securityProperties.getTokenHeader());

        // 获取请求的用户类型
        Integer requestUserType = WebUtils.getLoginUserType(request);
        if (requestUserType == null) {
            chain.doFilter(request, response);
            return;
        }

        if (StringUtils.hasText(token)) {
            // 验证访问令牌
            OAuth2AccessToken accessToken = accessTokenGateway.getByAccessToken(token);
            if (accessToken != null) {
                accessToken.isExpired();
                // 用户类型不匹配，无权限
                if (ObjectUtil.notEqual(accessToken.getUserType(), requestUserType)) {
                    WebUtils.writeJSON(response, ErrorCodeConstants.FORBIDDEN);
                    return;
                }
                // 构建登录用户
                LoginUser loginUser = LoginUser.create(accessToken.getUserId(), accessToken.getUserType(), accessToken.getTenantId(), accessToken.getScopes());
                SecurityUtils.setLoginUser(loginUser, request);
            }
        }
        chain.doFilter(request, response);
    }


}
